;================================================================
;  hrg.s
;               High resolution graphic mode display
;
;================================================================
;
; 25thanni, a demo dedicated to the 25th anniversary of the ZX81.
;
; (c)2006 Bodo Wenzel
;
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License as
; published by the Free Software Foundation; either version 2 of
; the License, or (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with this program; if not, write to the Free
; Software Foundation Inc., 59 Temple Place, Suite 330, Boston,
; MA 02111-1307 USA
;================================================================

	.module	hrg

;= Externals ====================================================

	.globl	hrg_file

	.globl	M_TOP
	.globl	M_BOTTOM
	.globl	vsync

	.globl	DELAY_OFFSET
	.globl	delay

;= Constants ====================================================

HRG_WIDTH	==	256
HRG_HEIGHT	==	192
PIXEL_PER_CLOCK	==	2

BYTES_PER_WORD	=	2

FALL_SPEED	=	4

;= Program code =================================================

	.area	CODE

;- Standard HRG screen routine ----------------------------------
; This needs hrg_file set to the stack of addresses for the
; display to be shown.

show_hrg::
	.dw	0
sh_p_top	=	.
	.db	M_TOP-2
sh_p_bottom	=	.
	.db	M_BOTTOM

	ld	a,#367+DELAY_OFFSET
sh_s_count	=	.+1
	ld	b,#1
	dec	b
	jr	z,sh_delay	; -5
	ld	a,b		; 4
	ld	(sh_s_count),a	; 13
	dec	a		; 4

	ld	a,(sh_p_top)	; 13
	jr	nz,sh_a_change	; 12/7
	jr	sh_a_last	; 12
sh_a_change:
sh_s_top	=	.+1
	add	#0		; 7
sh_a_last:
	ld	(sh_p_top),a	; 13

	ld	a,(sh_p_bottom)	; 13
sh_s_bottom	=	.+1
	add	#0		; 7
	ld	(sh_p_bottom),a	; 13

	ld	a,(sh_p_lines)	; 13
sh_s_lines	=	.+1
	add	#0		; 7
	ld	(sh_p_lines),a	; 13

	ld	hl,(sh_p_offset); 16
sh_s_offset	=	.+1
	ld	de,#0		; 10
	add	hl,de		; 11
	ld	(sh_p_offset),hl; 16

	ld	a,#367-187+DELAY_OFFSET ; 7
				; = 187
sh_delay:
	call	delay

	ld	hl,#0
	add	hl,sp
	ld	(sh_p_stack),hl

	ld	hl,(hrg_file)
sh_p_offset	=	.+1
	ld	de,#0
	add	hl,de
	ld	sp,hl
sh_p_lines	=	.+1
	ld	b,#HRG_HEIGHT
sh_loop:
	ld	hl,#sh_next	; 10
	jp	.+0x8003	; 10
	pop	de		; 10
	ld	a,d		; 4
	ld	i,a		; 9
	ld	a,e		; 4
	ld	r,a		; 9
	.db	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.db	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	; 32*4
	jp	(hl)		; 4
sh_next:
	inc	hl		; 6 (dummy)
	djnz	sh_loop		; 13

sh_p_stack	=	.+1
	ld	sp,#0
	ret

;- Reset roll mode to full display ------------------------------

	.if	0		; not used  - - - - - - - - - - -

h_reset::
	ld	hl,#hr_table
	jr	set_roll

hr_table:
	.db	1		; for sh_s_count
	.db	0		; for sh_s_top
	.db	M_TOP-2		; for sh_p_top
	.db	0		; for sh_s_bottom
	.db	M_BOTTOM	; for sh_p_bottom
	.dw	0		; for sh_s_offset
	.dw	0		; for sh_p_offset
	.db	0		; for sh_s_lines
	.db	HRG_HEIGHT	; for sh_p_lines

	.endif			; not used  - - - - - - - - - - -

;- Roll HRG in from the bottom ----------------------------------

h_in_up::
	ld	hl,#hiu_table
	jr	set_roll

hiu_table:
	.db	HRG_HEIGHT+1		; for sh_s_count
	.db	-1			; for sh_s_top
	.db	M_TOP-2+HRG_HEIGHT-1	; for sh_p_top
	.db	0			; for sh_s_bottom
	.db	M_BOTTOM		; for sh_p_bottom
	.dw	-BYTES_PER_WORD		; for sh_s_offset
	.dw	HRG_HEIGHT*BYTES_PER_WORD	; for sh_p_offset
	.db	+1			; for sh_s_lines
	.db	0			; for sh_p_lines

;- Roll HRG out from the bottom ---------------------------------

h_out_up::
	ld	hl,#hou_table
	jr	set_roll

hou_table:
	.db	HRG_HEIGHT+1		; for sh_s_count
	.db	0			; for sh_s_top
	.db	M_TOP-2			; for sh_p_top
	.db	+1			; for sh_s_bottom
	.db	M_BOTTOM-1		; for sh_p_bottom
	.dw	0			; for sh_s_offset
	.dw	0			; for sh_p_offset
	.db	-1			; for sh_s_lines
	.db	HRG_HEIGHT+1		; for sh_p_lines

;- Roll HRG in from the top -------------------------------------

h_in_down::
	ld	hl,#hid_table
	jr	set_roll

hid_table:
	.db	HRG_HEIGHT+1		; for sh_s_count
	.db	0			; for sh_s_top
	.db	M_TOP-2			; for sh_p_top
	.db	-1			; for sh_s_bottom
	.db	M_BOTTOM+HRG_HEIGHT	; for sh_p_bottom
	.dw	0			; for sh_s_offset
	.dw	0			; for sh_p_offset
	.db	+1			; for sh_s_lines
	.db	0			; for sh_p_lines

;- Roll HRG out from the top ------------------------------------

h_out_down::
	ld	hl,#hod_table
	jr	set_roll

hod_table:
	.db	HRG_HEIGHT+1		; for sh_s_count
	.db	+1			; for sh_s_top
	.db	M_TOP-2			; for sh_p_top
	.db	0			; for sh_s_bottom
	.db	M_BOTTOM		; for sh_p_bottom
	.dw	+BYTES_PER_WORD		; for sh_s_offset
	.dw	-BYTES_PER_WORD		; for sh_p_offset
	.db	-1			; for sh_s_lines
	.db	HRG_HEIGHT+1		; for sh_p_lines

;- Let HRG fall in from the top ---------------------------------

h_in_fall::
	ld	hl,#hif_table
	jr	set_roll

hif_table:
	.db	HRG_HEIGHT/FALL_SPEED+1	; for sh_s_count
	.db	0			; for sh_s_top
	.db	M_TOP-2			; for sh_p_top
	.db	-FALL_SPEED		; for sh_s_bottom
	.db	M_BOTTOM+HRG_HEIGHT	; for sh_p_bottom
	.dw	-FALL_SPEED*BYTES_PER_WORD	; for sh_s_offset
	.dw	HRG_HEIGHT*BYTES_PER_WORD	; for sh_p_offset
	.db	+FALL_SPEED		; for sh_s_lines
	.db	0			; for sh_p_lines

;- Roll HRG out into the center like a dying TV -----------------

h_out_center::
	ld	hl,#hoc_table
	jr	set_roll

hoc_table:
	.db	HRG_HEIGHT/2+1		; for sh_s_count
	.db	+1			; for sh_s_top
	.db	M_TOP-2			; for sh_p_top
	.db	+1			; for sh_s_bottom
	.db	M_BOTTOM-1		; for sh_p_bottom
	.dw	+BYTES_PER_WORD		; for sh_s_offset
	.dw	-BYTES_PER_WORD		; for sh_p_offset
	.db	-2			; for sh_s_lines
	.db	HRG_HEIGHT+2		; for sh_p_lines

;- Set up roll mode ---------------------------------------------

set_roll:
	push	hl
	call	vsync
	pop	hl

	ld	a,(hl)
	inc	hl
	ld	(sh_s_count),a

	ld	a,(hl)
	inc	hl
	ld	(sh_s_top),a
	ld	a,(hl)
	inc	hl
	ld	(sh_p_top),a

	ld	a,(hl)
	inc	hl
	ld	(sh_s_bottom),a
	ld	a,(hl)
	inc	hl
	ld	(sh_p_bottom),a

	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(sh_s_offset),de
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(sh_p_offset),de

	ld	a,(hl)
	inc	hl
	ld	(sh_s_lines),a
	ld	a,(hl)
	inc	hl
	ld	(sh_p_lines),a

	ret

;- Wait for roll mode to finish ---------------------------------

	.if	0		; not used  - - - - - - - - - - -

h_ready::
	ld	a,(sh_s_count)
	dec	a
	jr	nz,h_ready
	ret

	.endif			; not used  - - - - - - - - - - -

;- Check whether roll mode has finished -------------------------
; Uses AF
; Returns Z set if roll mode has finished

h_check::
	ld	a,(sh_s_count)
	dec	a
	ret

;= The end ======================================================
